// API 路由器 - 基于 DSL 模型自动生成 REST API

import express, { Router, Request, Response, NextFunction } from 'express';
import { DomainModel, EntityDef, ValidationError } from '@domain-craft/shared-types';
import { DSLValidator } from '../../../../packages/dsl-parser/src/validator.js';

export interface APIRouterConfig {
  basePath?: string;
  enableValidation?: boolean;
  enableCORS?: boolean;
  maxRequestSize?: string;
}

export interface EntityRepository {
  findAll(): Promise<any[]>;
  findById(id: string | number): Promise<any | null>;
  create(data: any): Promise<any>;
  update(id: string | number, data: any): Promise<any>;
  delete(id: string | number): Promise<boolean>;
}

export interface RepositoryFactory {
  getRepository(entityName: string): EntityRepository;
}

/**
 * API 路由器类
 * 根据领域模型自动生成 REST API 端点
 */
export class APIRouter {
  private router: Router;
  private model: DomainModel;
  private repositoryFactory: RepositoryFactory;
  private config: APIRouterConfig;

  constructor(
    model: DomainModel,
    repositoryFactory: RepositoryFactory,
    config: APIRouterConfig = {}
  ) {
    this.router = express.Router();
    this.model = model;
    this.repositoryFactory = repositoryFactory;
    this.config = {
      basePath: '/api',
      enableValidation: true,
      enableCORS: true,
      maxRequestSize: '10mb',
      ...config
    };

    this.setupMiddleware();
    this.generateRoutes();
  }

  /**
   * 获取 Express 路由器
   */
  getRouter(): Router {
    return this.router;
  }

  /**
   * 设置中间件
   */
  private setupMiddleware(): void {
    // JSON 解析
    this.router.use(express.json({ limit: this.config.maxRequestSize }));
    this.router.use(express.urlencoded({ extended: true, limit: this.config.maxRequestSize }));

    // CORS 支持
    if (this.config.enableCORS) {
      this.router.use((req: Request, res: Response, next: NextFunction) => {
        res.header('Access-Control-Allow-Origin', '*');
        res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
        res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
        
        if (req.method === 'OPTIONS') {
          res.sendStatus(200);
        } else {
          next();
        }
      });
    }

    // 错误处理中间件
    this.router.use(this.errorHandler.bind(this));
  }

  /**
   * 根据领域模型生成路由
   */
  private generateRoutes(): void {
    if (!this.model.entities) {
      return;
    }

    // 为每个实体生成 CRUD 路由
    Object.entries(this.model.entities).forEach(([entityName, entityDef]) => {
      this.generateEntityRoutes(entityName, entityDef);
    });

    // 生成健康检查端点
    this.router.get('/health', this.healthCheck.bind(this));

    // 生成模型信息端点
    this.router.get('/model', this.getModelInfo.bind(this));
  }

  /**
   * 为单个实体生成 CRUD 路由
   */
  private generateEntityRoutes(entityName: string, entityDef: EntityDef): void {
    const basePath = `/${this.pluralize(entityName.toLowerCase())}`;
    const repository = this.repositoryFactory.getRepository(entityName);

    // GET /entities - 获取所有实体
    this.router.get(basePath, async (req: Request, res: Response, next: NextFunction) => {
      try {
        const entities = await repository.findAll();
        res.json({
          success: true,
          data: entities,
          count: entities.length
        });
      } catch (error) {
        next(error);
      }
    });

    // GET /entities/:id - 获取单个实体
    this.router.get(`${basePath}/:id`, async (req: Request, res: Response, next: NextFunction) => {
      try {
        const entity = await repository.findById(req.params.id);
        if (!entity) {
          return res.status(404).json({
            success: false,
            error: `${entityName} not found`
          });
        }
        res.json({
          success: true,
          data: entity
        });
      } catch (error) {
        next(error);
      }
    });

    // POST /entities - 创建新实体
    this.router.post(basePath, async (req: Request, res: Response, next: NextFunction) => {
      try {
        // 验证请求数据
        if (this.config.enableValidation) {
          const validationErrors = this.validateEntityData(req.body, entityDef, entityName);
          if (validationErrors.length > 0) {
            return res.status(400).json({
              success: false,
              error: 'Validation failed',
              details: validationErrors
            });
          }
        }

        const entity = await repository.create(req.body);
        res.status(201).json({
          success: true,
          data: entity
        });
      } catch (error) {
        next(error);
      }
    });

    // PUT /entities/:id - 更新实体
    this.router.put(`${basePath}/:id`, async (req: Request, res: Response, next: NextFunction) => {
      try {
        // 验证请求数据
        if (this.config.enableValidation) {
          const validationErrors = this.validateEntityData(req.body, entityDef, entityName);
          if (validationErrors.length > 0) {
            return res.status(400).json({
              success: false,
              error: 'Validation failed',
              details: validationErrors
            });
          }
        }

        const entity = await repository.update(req.params.id, req.body);
        if (!entity) {
          return res.status(404).json({
            success: false,
            error: `${entityName} not found`
          });
        }

        res.json({
          success: true,
          data: entity
        });
      } catch (error) {
        next(error);
      }
    });

    // DELETE /entities/:id - 删除实体
    this.router.delete(`${basePath}/:id`, async (req: Request, res: Response, next: NextFunction) => {
      try {
        const success = await repository.delete(req.params.id);
        if (!success) {
          return res.status(404).json({
            success: false,
            error: `${entityName} not found`
          });
        }

        res.json({
          success: true,
          message: `${entityName} deleted successfully`
        });
      } catch (error) {
        next(error);
      }
    });
  }

  /**
   * 验证实体数据
   */
  private validateEntityData(data: any, entityDef: EntityDef, entityName: string): ValidationError[] {
    return DSLValidator.validateEntityData(data, entityDef, entityName, this.model.enums);
  }

  /**
   * 健康检查端点
   */
  private healthCheck(req: Request, res: Response): void {
    res.json({
      success: true,
      status: 'healthy',
      timestamp: new Date().toISOString(),
      version: this.model.version,
      domain: this.model.domain
    });
  }

  /**
   * 获取模型信息端点
   */
  private getModelInfo(req: Request, res: Response): void {
    const entityNames = Object.keys(this.model.entities || {});
    const enumNames = (this.model.enums || []).map(e => e.name);

    res.json({
      success: true,
      data: {
        domain: this.model.domain,
        version: this.model.version,
        description: this.model.description,
        entities: entityNames,
        enums: enumNames,
        entityCount: entityNames.length,
        enumCount: enumNames.length
      }
    });
  }

  /**
   * 错误处理中间件
   */
  private errorHandler(error: any, req: Request, res: Response, next: NextFunction): void {
    console.error('API Error:', error);

    // 如果响应已经发送，则交给默认错误处理器
    if (res.headersSent) {
      return next(error);
    }

    // 根据错误类型返回适当的状态码
    let statusCode = 500;
    let message = 'Internal server error';

    if (error.name === 'ValidationError') {
      statusCode = 400;
      message = 'Validation failed';
    } else if (error.name === 'NotFoundError') {
      statusCode = 404;
      message = 'Resource not found';
    } else if (error.message) {
      message = error.message;
    }

    res.status(statusCode).json({
      success: false,
      error: message,
      ...(process.env.NODE_ENV === 'development' && { stack: error.stack })
    });
  }

  /**
   * 简单的复数化函数
   */
  private pluralize(word: string): string {
    if (word.endsWith('y')) {
      return word.slice(0, -1) + 'ies';
    } else if (word.endsWith('s') || word.endsWith('sh') || word.endsWith('ch') || word.endsWith('x') || word.endsWith('z')) {
      return word + 'es';
    } else {
      return word + 's';
    }
  }
}

/**
 * 创建 API 路由器的工厂函数
 */
export function createAPIRouter(
  model: DomainModel,
  repositoryFactory: RepositoryFactory,
  config?: APIRouterConfig
): Router {
  const apiRouter = new APIRouter(model, repositoryFactory, config);
  return apiRouter.getRouter();
}

/**
 * 默认的内存仓储实现（用于测试和开发）
 */
export class InMemoryRepository implements EntityRepository {
  private data: Map<string | number, any> = new Map();
  private nextId = 1;

  async findAll(): Promise<any[]> {
    return Array.from(this.data.values());
  }

  async findById(id: string | number): Promise<any | null> {
    return this.data.get(id) || null;
  }

  async create(data: any): Promise<any> {
    const id = this.nextId++;
    const entity = { id, ...data };
    this.data.set(id, entity);
    return entity;
  }

  async update(id: string | number, data: any): Promise<any> {
    const existing = this.data.get(id);
    if (!existing) {
      return null;
    }
    const updated = { ...existing, ...data };
    this.data.set(id, updated);
    return updated;
  }

  async delete(id: string | number): Promise<boolean> {
    return this.data.delete(id);
  }
}

/**
 * 默认的仓储工厂实现
 */
export class InMemoryRepositoryFactory implements RepositoryFactory {
  private repositories: Map<string, EntityRepository> = new Map();

  getRepository(entityName: string): EntityRepository {
    if (!this.repositories.has(entityName)) {
      this.repositories.set(entityName, new InMemoryRepository());
    }
    return this.repositories.get(entityName)!;
  }
}